Public Class JoinDesignerTable
    Private _DoMove As Boolean = False
    Private _MousDownLocation As New Drawing.Point
    Protected _minWidth As Integer = 64

    Protected _Owner As JoinDesigner
    Protected WithEvents _Represents As Metis.Core.Functions.MetisRefFunction

    ''' <summary>
    ''' Raised when a new  join is created after a Drag-n-Drop operation
    ''' </summary>
    ''' <param name="Sender">The JoinDesignerTable-Object</param>
    ''' <param name="e">Contains information of the new created join</param>
    ''' <remarks></remarks>
    Public Event JoinCreated(ByVal Sender As Object, ByVal e As JoinDesignerJoinEventArgs)
    Public Event TableMoving(ByVal e As JoinDesignerTableEventArgs)
    Public Event TableMoved(ByVal e As JoinDesignerTableEventArgs)


    Sub New(ByVal Represents As Metis.Core.Functions.MetisRefFunction, ByVal Owner As JoinDesigner)
        InitializeComponent()
        Me._Represents = Represents
        Me._Owner = Owner
        Me.TableCaption.Text = _Represents.ToString
        FieldList.DataSource = _Represents.ReferencedFunction.Fields
        ResizeTableDimensions()
    End Sub

    Private Sub ResizeTableDimensions()

        Me.Height = Me.FieldList.Location.Y + Me.FieldList.Items.Count * Me.FieldList.ItemHeight + 4


        Dim tmpGrafic As System.Drawing.Graphics = Me.TableCaption.CreateGraphics
        Dim w As Double = Math.Max(tmpGrafic.MeasureString(Me.TableCaption.Text, Me.TableCaption.Font).Width * 1.2, _minWidth)


        For Each item As Metis.Core.Functions.MetisFunctionField In Me.FieldList.Items
            If tmpGrafic.MeasureString(item.ToString, New System.Drawing.Font(FieldList.Font, FontStyle.Bold)).Width * 1.2 > w Then
                w = tmpGrafic.MeasureString(item.ToString, New System.Drawing.Font(FieldList.Font, FontStyle.Bold)).Width * 1.2
            End If
        Next
        Me.Width = CInt(Math.Round(w, MidpointRounding.AwayFromZero))
    End Sub

    Private Sub HandleUsedFunctionRemove(ByVal sender As Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles _Represents.FieldListChange
        ResizeTableDimensions()
    End Sub

    Public Overrides Function ToString() As String
        Return _Represents.ToString
    End Function

    Sub Add(ByVal Field As Metis.Core.Functions.MetisFunctionField)
        'Me.FieldList.Items.Add(Field)
        'Me.Height = Me.FieldList.Location.Y + Me.FieldList.Items.Count * Me.FieldList.ItemHeight + 4


        'Dim tmpGrafic As System.Drawing.Graphics = Me.TableCaption.CreateGraphics
        'Dim w As Double = Math.Max(tmpGrafic.MeasureString(Me.TableCaption.Text, Me.TableCaption.Font).Width * 1.2, _minWidth)
        ''tmpGrafic = Me.FieldList.CreateGraphics

        'For Each item As DAMfunctionField In Me.FieldList.Items
        '    If tmpGrafic.MeasureString(item.ToString, New System.Drawing.Font(FieldList.Font, FontStyle.Bold)).Width * 1.2 > w Then
        '        w = tmpGrafic.MeasureString(item.ToString, New System.Drawing.Font(FieldList.Font, FontStyle.Bold)).Width * 1.2
        '    End If
        'Next
        'Me.Width = CInt(Math.Round(w, MidpointRounding.AwayFromZero))
    End Sub

    Private Sub TableCaption_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TableCaption.MouseDown
        _DoMove = True
        _MousDownLocation = New Drawing.Point(e.Location.X, e.Location.Y)
    End Sub

    Private Sub TableCaption_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TableCaption.MouseMove
        If Me._DoMove Then
            Me.Location = New Drawing.Point(Me.Location.X + e.Location.X - _MousDownLocation.X, Me.Location.Y + e.Location.Y - _MousDownLocation.Y)
            RaiseEvent TableMoving(New JoinDesignerTableEventArgs(Me, Me.Location))
            Me.Parent.Refresh()
        End If
    End Sub

    Private Sub TableCaption_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TableCaption.MouseUp
        If Me._DoMove Then
            _DoMove = False
            Me.Location = New Drawing.Point(Math.Max(0, Me.Location.X + e.Location.X - _MousDownLocation.X), Math.Max(0, Me.Location.Y + e.Location.Y - _MousDownLocation.Y))
            RaiseEvent TableMoved(New JoinDesignerTableEventArgs(Me, Me.Location))
        End If
    End Sub

    Public Property Represents() As Core.Functions.MetisRefFunction
        Get
            Return _Represents
        End Get
        Set(ByVal value As Core.Functions.MetisRefFunction)
            _Represents = value
            Me.TableCaption.Text = _Represents.ToString
        End Set
    End Property

    Public Property Fields(ByVal i As Integer) As Core.Functions.MetisFunctionField
        Get
            Return DirectCast(Me.FieldList.Items(i), Core.Functions.MetisFunctionField)
        End Get
        Set(ByVal value As Core.Functions.MetisFunctionField)
            Me.FieldList.Items(i) = value
        End Set
    End Property

    Public ReadOnly Property FieldLocation(ByVal item As Metis.Core.Functions.MetisFunctionField) As Drawing.Point
        Get
            Return New Drawing.Point(_Owner.Location.X, Me.Location.Y + FieldList.Location.Y + FieldList.ItemHeight * FieldList.Items.IndexOf(item))
        End Get
    End Property

    Public ReadOnly Property FieldCount() As Integer
        Get
            Return Me.FieldList.Items.Count
        End Get
    End Property


    Private Sub FieldList_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles FieldList.MouseDown
        FieldList.DoDragDrop(FieldList.SelectedItem, DragDropEffects.Move)
    End Sub

    Private Sub FieldList_DragEnter(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles FieldList.DragEnter
        If e.Data.GetDataPresent(GetType(Metis.Core.Functions.MetisFunctionField)) AndAlso Not DirectCast(e.Data.GetData(GetType(Metis.Core.Functions.MetisFunctionField)), Metis.Core.Functions.MetisFunctionField).Function.Equals(_Represents) Then
            e.Effect = DragDropEffects.Move
        End If
    End Sub

    Private Sub FieldList_DragDrop(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles FieldList.DragDrop

        If e.Data.GetDataPresent(GetType(Metis.Core.Functions.MetisFunctionField)) AndAlso Not DirectCast(e.Data.GetData(GetType(Metis.Core.Functions.MetisFunctionField)), Metis.Core.Functions.MetisFunctionField).Function.Equals(Me.Represents) Then

            Dim tmpLeftField As Metis.Core.Functions.MetisFunctionField = DirectCast(e.Data.GetData(GetType(Metis.Core.Functions.MetisFunctionField)), Metis.Core.Functions.MetisFunctionField)



            FieldList.SelectedIndex = CType(Math.Max(0, Math.Min(Math.Truncate(FieldList.PointToClient(New System.Drawing.Point(e.X, e.Y)).Y / FieldList.ItemHeight), FieldList.Items.Count - 1)), Integer)

            Dim tmpRightField As Metis.Core.Functions.MetisFunctionField = DirectCast(FieldList.SelectedItem, Metis.Core.Functions.MetisFunctionField)

            RaiseEvent JoinCreated(Me, New JoinDesignerJoinEventArgs(tmpLeftField, tmpRightField, Metis.Core.Functions.MetisJoinType.InnerJoin))
        End If
    End Sub

    Private Sub TableCaption_MouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles TableCaption.MouseClick
        If e.Button = Windows.Forms.MouseButtons.Right AndAlso Not ContextMenuStrip Is Nothing Then
            Me.ContextMenuStrip.Show(New System.Drawing.Point(e.X, e.Y))
        End If
    End Sub
End Class



Public Class JoinDesignerJoinEventArgs
    Inherits EventArgs

    Public _LeftJoinField As Metis.Core.Functions.MetisFunctionField
    Public _RightJoinField As Metis.Core.Functions.MetisFunctionField
    Public _JoinType As Metis.Core.Functions.MetisJoinType

    Sub New(ByVal LeftField As Metis.Core.Functions.MetisFunctionField, ByVal RightField As Metis.Core.Functions.MetisFunctionField, ByVal NewJoinType As Metis.Core.Functions.MetisJoinType)
        _LeftJoinField = LeftField
        _RightJoinField = RightField
        _JoinType = NewJoinType
    End Sub

    Public ReadOnly Property LeftJoinField() As Metis.Core.Functions.MetisFunctionField
        Get
            Return _LeftJoinField
        End Get
    End Property

    Public ReadOnly Property RightJoinField() As Metis.Core.Functions.MetisFunctionField
        Get
            Return _RightJoinField
        End Get
    End Property

    Public ReadOnly Property JoinType() As Metis.Core.Functions.MetisJoinType
        Get
            Return _JoinType
        End Get
    End Property
End Class

